#include <atomic>
template<class T>
class spsc
{
public:

	spsc(T * para1, int size) :slot(para1), m_write(0),m_read(0),capacity(size),flag(0)
	{
	}

	template <typename ... Args >
	void push(Args && ... args)
	{
		auto const writeIndex = m_write.load(memory_order_relaxed);



		if (writeIndex == capacity)
		{
			writeIndex = 0;
		}
		if (writeIndex == m_read.load(memory_order_acquire) && 1 == flag.load(memory_order_acquire)) //已队满
		{
			return ;
		}
		//if (writeIndex<m_read.load(memory_order_acquire))
		{
			new (&slot[writeIndex])  T(std::forward<Args>(args)...);
			writeIndex = writeIndex + 1;
			if (writeIndex == m_read.load(memory_order_acquire) )
			{
				flag.store(1,memory_order_release);//队满
			}
			m_write.store(writeIndex,memory_order_release);
		}
	}
	T * read()
	{
		auto const readIndex = m_read.load(memory_order_relaxed);

		///队空 且index相等时 没有数据可拿   否则就是有数据
		if (readIndex == m_write.load(memory_order_acquire)  && 0==flag.load(memory_order_acquire))
		{
			return nullptr;
		}
//		if (readIndex < m_write.load(memory_order_acquire)) //没有成环时  这种情况才会有数据可拿
		{
			readIndex = readIndex + 1;
			m_read.store(readIndex,memory_order_release);
			if (readIndex == m_write.load(memory_order_acquire))
			{
				flag.store(0, memory_order_release);//队空
			}
			return &slot[readIndex - 1];
		}
		else
		{
			return nullptr;
		}
	}
	atomic<int > m_write;
	atomic<int > m_read;
	int capacity;
	atomic <int> flag;//0  队空  1队满
	T *slot;
};
